/*
 * Ambiente.h
 *
 *  Created on: 25-10-2011
 *      Author: cristian
 */

#ifndef AMBIENTE_H_
#define AMBIENTE_H_

#include <stdio.h>
#include <stdlib.h>

#include "Worker.h"
#include "Logger.h"
#include <list>
#include <pthread.h>

template <typename T> class Ambiente {

protected:

	Logger* logger;
	T*** ambiente;
	unsigned int x;
	unsigned int y;
	list<T*> workers;
	pthread_mutex_t mutex;

public:

	Ambiente();
	virtual ~Ambiente();
	Ambiente(unsigned int x, unsigned int y);
	void trace();
	void setNodo(unsigned int x, unsigned int y, T* nodo);
	T* getNodo(unsigned int x, unsigned int y);

    list<T*> getWorkers() const;
    void setWorkers(list<T*> workers);
    unsigned int getX() const;
    unsigned int getY() const;
    void setX(unsigned int x);
    void setY(unsigned int y);
    void mergePos(unsigned int x1, unsigned int y1, unsigned int x2, unsigned int y2);

};



template<typename T>  Ambiente<T>::Ambiente()
{
	 pthread_mutex_init(&mutex, NULL);
	this->logger = new Logger();
	this->ambiente = (T***) malloc(getX() * sizeof(T**));

	int i;
	for (i = 0; i < getX() ; i++) {
		this->ambiente[i] = (T**) malloc(getY() * sizeof(T*));
	}
}


template<typename T>  Ambiente<T>::~Ambiente()
{
}



template<typename T>  Ambiente<T>::Ambiente(unsigned int x, unsigned int y)
{

	setX(x);
	setY(y);

	this->logger = new Logger();

		this->ambiente = (T***) malloc(getX() * sizeof(T**));
		int i;
		for (i = 0; i < getX() ; i++) {
			this->ambiente[i] = (T**) malloc(getY() * sizeof(T*));
		}

		int j;
		int f;
		for (j= 0; j<getX(); ++j){
			for (f= 0; f<getY(); ++f){
				this->ambiente[j][f] = NULL;
			}
		}



#ifdef TRACE
		HAL_TRACE(this->logger," (%i,%i )", getX(), getY());

#endif
}



template<typename T>  void Ambiente<T>::trace()
{
#ifdef TRACE

		HAL_TRACE(this->logger, "X %i", getX());
		HAL_TRACE(this->logger, "Y %i", getY());

		int i;
		int j;
		for (i = 0; i < getX(); i++) {
			for (j = 0; j < getY(); j++) {
				HAL_TRACE(this->logger, " (%i,%i) ", i, j);
			}
			printf("\n");
		}
#endif
}



template<typename T>  void Ambiente<T>::setNodo(unsigned int x, unsigned int y, T *nodo)
{

	pthread_mutex_lock(&mutex);

	 workers.push_front(nodo);


#ifdef TRACE
	HAL_TRACE(this->logger, "(%i,%i) ", x,y);
#endif



	if (x < getX() && y < getY() && x >= 0 && y >=0 ){

		this->ambiente[x][y] = nodo;
	}
	 pthread_mutex_unlock(&mutex);

}



template<typename T> unsigned int Ambiente<T>::getX() const
{
    return x;
}


template<typename T> unsigned int Ambiente<T>::getY() const
{
    return y;
}


template<typename T> void Ambiente<T>::setX(unsigned int x)
{
    this->x = x;
}


template<typename T> void Ambiente<T>::setY(unsigned int y)
{
    this->y = y;
}

template<typename T>  T *Ambiente<T>::getNodo(unsigned int x, unsigned int y)
{

	return this->ambiente[x][y];

}


template<typename T> inline list<T*> Ambiente<T>::getWorkers() const
{
	return this->workers;
}

template<typename T> inline void Ambiente<T>::mergePos(unsigned int x1, unsigned int y1, unsigned int x2, unsigned int y2)
{

}





#endif /* AMBIENTE_H_ */
